package com.glsc.ngateway.common.base.utils;


import cn.hutool.core.util.StrUtil;
import com.vdurmont.emoji.EmojiManager;
import com.vdurmont.emoji.EmojiParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zhouzp
 * @date 2024/1/2
 * Emoji工具类
 */
public class MyEmojiTool {
    private static Logger logger = LoggerFactory.getLogger(MyEmojiTool.class);

    public static void main(String[] args) {
        String longText = "\uD83D\uDE04\uD83D\uDE04\uD83D\uDE04A\uD83D\uDE04超test超长字符串1234567890";
        //示例字符串：
        //"\uD83D\uDE04\uD83D\uDE04\uD83D\uDE04A\uD83D\uDE04超test超长字符串1234567890"
        //分隔为：[😄😄, 😄A😄, 超test超, 长字符, 串1234567, 890]
        List<String> textList = null;
        textList = stringSplitByByteLength(longText, 10);
        System.out.println(textList);

        longText = "\uD83D\uDE04\uD83D\uDE04";
        textList = stringSplitByByteLength(longText, 10);
        System.out.println(textList);

    }

    public static List<String> stringSplitByByteLength(String srcString, int byteLength) {
        return stringSplitByByteLength(srcString, "utf-8", byteLength);
    }

    /**
     * 根据字节数分隔字符串，最后一个字节如果是汉字、Emoji也兼容
     * 示例字符串：
     * "\uD83D\uDE04\uD83D\uDE04\uD83D\uDE04A\uD83D\uDE04超test超长字符串1234567890"
     * 分隔为：[😄😄, 😄A😄, 超test超, 长字符, 串1234567, 890]
     */
    public static List<String> stringSplitByByteLength(String srcString, String byteType, int byteLength) {
        if (srcString == null) {
            return null;
        }
        List<String> splitList = new ArrayList<>();

        boolean hasEmoji = containsEmoji(srcString);
        int stringLengthEmoji = stringLengthEmoji(srcString);//兼容emoji的字符串长度

        int startIndex = 0; //字符串截取起始位置
        int endIndex = Math.min(hasEmoji ? stringLengthEmoji : srcString.length(), byteLength);// 字符串截取结束位置
        logger.info("字符串：hasEmoji={}，endIndex={}", hasEmoji, endIndex);
        int loopCnt = 0;
        try {
            while (startIndex < stringLengthEmoji) {
                loopCnt++;

                String tempSubString = hasEmoji ? substringEmoji(srcString, startIndex, endIndex) : srcString.substring(startIndex, endIndex);

                //截取的字符串的字节长度大于需要截取的长度时，说明包含中文字符
                // 在GBK编码中，一个中文字符占2个字节，UTF-8编码格式，一个中文字符占3个字节、Emoj占4个字节。
                while (tempSubString.getBytes(byteType).length > byteLength) {
                    loopCnt++;
                    --endIndex;//TODO ，这里每次回退1个汉字，效率比较低，考虑一次性回退更多
//                    subString = srcString.substring(startIndex, endIndex);
                    tempSubString = hasEmoji ? substringEmoji(srcString, startIndex, endIndex) : srcString.substring(startIndex, endIndex);
                }
                splitList.add(tempSubString);

                startIndex = endIndex;
                endIndex = Math.min(stringLengthEmoji, startIndex + byteLength);// (startIndex + byteLength) > srcString.length() ? srcString.length() : startIndex + byteLength;
                if (loopCnt > 100 * 10000) {
                    throw new RuntimeException("遍历次数过多，疑似异常，终止");
                }
            }
        } catch (Exception e) {
            logger.error("分隔字符串异常：{}", e);
        }
        logger.info("处理次数：{}", loopCnt);
        return splitList;
    }

    /**
     * 英文字母、汉字、Emoji表情均视为一个字符
     * 支持Emoji的字符串截取
     * emoji表情是用两个char存储（4个字节），常规的substring是按照char截取的，就有可能只截取了半个Emoji表情
     */
    public static String substringEmoji(String source, int start, int end) {
        if (StrUtil.isEmpty(source) || start > end) {
            return "";
        }

        String result;
        try {
            result = source.substring(source.offsetByCodePoints(0, start),
                    source.offsetByCodePoints(0, end));
        } catch (Exception e) {
            result = "";
        }
        return result;
    }

    /**
     * 判断字符串是否包含Emoji表情
     */
    public static boolean containsEmoji(String str) {
        return EmojiManager.containsEmoji(str);
    }

    /**
     * 支持Emoji的字符串长度计算，一个emoji表情、一个汉字均视为一个字符。
     */
    public static int stringLengthEmoji(String source) {
        if (StrUtil.isEmpty(source)) {
            return 0;
        }
        int strLength = source.length();
        if (EmojiManager.containsEmoji(source)) {//原始的"".length()会把一个emoji表情统计为2个字符
            List<String> emojiList = EmojiParser.extractEmojis(source);
            strLength = strLength - emojiList.size();
        }
        return strLength;
    }

    /**
     * 提取Emoji字符列表
     */
    public static List<String> extractEmojis(String str) {
        return EmojiParser.extractEmojis(str);
    }
}


